package com.oa.web.action;

import com.oa.utils.DBUtil;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;


// 注意：oa2改造oa1：注解式开发解决xml中Servlet过多+模板方法设计模式(把类改造成方法)解决类爆炸
// 1. 注解式开发：
// name 相当于xml文件中<servlet-name>，可以省略
// urlPatterns 相当于xml配置文件中<url-pattern>,一个Servlet可以有多个路径
// @WebServlet(name = "DeptServlet", urlPatterns = {})
// 2.模板方法设计模式：
// 重写service方法(可以同时处理前端发来的doGet和doPost方法的情况)，而不是doGet或doPost方法
// 解决类爆炸核心：让一个请求对应一个方法，而不是对应一个类
// 模糊匹配：@WebServlet({"/dept/*"})也可，只要是路径以/dept开头，都走这个路径，但是获取路径不能用getServletPath
//          getServletPath只能获取到"/dept"
@WebServlet({"/dept/list","/dept/save","/dept/delete","/dept/detail","/dept/edit","/dept/modify"})
public class DeptServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String servletPath = request.getServletPath();
        // 这里是判断是否登录登业务处理，不能新建session，只能判断，所以加上false
        HttpSession session = request.getSession(false);

        if(session!=null && session.getAttribute("username")!=null){
            if("/dept/list".equals(servletPath)){
                doList(request, response);
            }else if("/dept/save".equals(servletPath)){
                doSave(request, response);
            }else if("/dept/delete".equals(servletPath)){
                doDel(request, response);
            }else if("/dept/detail".equals(servletPath)){
                doDetail(request, response);
            }else if("/dept/modify".equals(servletPath)){
                doModify(request, response);
            }
        }else{
            // 还没有登录，转发到登录页面
            // 这里可以不加"/index.jsp"，因为访问项目时，会自动访问index.jsp文件
            response.sendRedirect(request.getContextPath() + "/index.jsp");
        }

    }

    /**
     * 连接数据库，查询所有部门的信息，将部门信息收集好，然后跳转到jsp做页面展示
     * @param request
     * @param response
     */
    private void doList(HttpServletRequest request, HttpServletResponse response){
        List<Dept> deptList = new ArrayList<>();

        //连接数据库，查询所有的部门
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //获取连接
            conn = DBUtil.getConnection();

            //获取数据库操作对象
            String sql = "select deptno,dname,loc from dept";
            ps = conn.prepareStatement(sql);

            //执行sql
            rs = ps.executeQuery();

            //处理结果集
            int i=0;
            while(rs.next()){
                String deptno = rs.getString("deptno");
                String dname = rs.getString("dname");
                String loc = rs.getString("loc");

                // 将以上零散的信息封装成java对象
                Dept dept = new Dept();
                dept.setDeptno(deptno);
                dept.setDname(dname);
                dept.setLoc(loc);

                // 把部门对象放入集合
                deptList.add(dept);
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            //释放资源
            DBUtil.close(conn,ps,rs);
        }

        // 最后把集合放进请求域中
        request.setAttribute("deptList",deptList);

        //获取应用的根路径
        String contextPath = request.getContextPath();

        // 使用转发(使用请求域，利用转发的一次请求,不能用重定向)，转发数据到list.jsp，做页面展示
        try {
            request.getRequestDispatcher("/list.jsp").forward(request,response);
        } catch (ServletException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 新增部门信息
     * @param request
     * @param response
     */
    private void doSave(HttpServletRequest request, HttpServletResponse response) throws IOException {
        request.setCharacterEncoding("UTF-8");

        String deptno = request.getParameter("deptno");
        String dname = request.getParameter("dname");
        String loc = request.getParameter("loc");

        Connection conn = null;
        PreparedStatement ps = null;
        //ResultSet rs = null;
        int row = 0;

        try {
            conn = DBUtil.getConnection();

            //下面这一行的deptno，dname,loc代表数据库中字段名
            String sql = "insert into dept value(?,?,?)";
            ps = conn.prepareStatement(sql);
            ps.setString(1,deptno);
            ps.setString(2,dname);
            ps.setString(3,loc);

            row = ps.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DBUtil.close(conn,ps,null);
        }

        if(row==1){
            /*
                注意：这里向数据库插入数据后，转发到/dept/list，而不是/list.jsp，因为插入数据后，应该重新查数据库数据
                    (删除类似)
            */
            response.sendRedirect(request.getContextPath()+"/dept/list");
        }else {
            response.sendRedirect(request.getContextPath() + "/error.jsp");

        }
    }

    /**
     * 根据部门编号删除部门
     * @param request
     * @param response
     */
    private void doDel(HttpServletRequest request, HttpServletResponse response) {
        // 获取部门编号
        String deptno = request.getParameter("deptno");

        // 连接数据库，删除部门
        Connection conn = null;
        PreparedStatement ps = null;
        //ResultSet rs = null;
        int row = 0;

        try {
            conn = DBUtil.getConnection();

            //开启事务
            conn.setAutoCommit(false);

            String sql = "delete from dept where deptno=?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,deptno);

            row = ps.executeUpdate();

            //事务提交
            conn.commit();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            //遇到异常回滚
            try {
                conn.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        } finally {
            DBUtil.close(conn,ps,null);
        }

        //判断是否删除成功
        if(row==1){
            try {
                response.sendRedirect(request.getContextPath() + "/dept/list");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            try {
                response.sendRedirect(request.getContextPath() + "/error.jsp");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据部门编号获取部门信息
     * @param request
     * @param response
     */
    private void doDetail(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            request.setCharacterEncoding("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = null;
        try {
            out = response.getWriter();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Dept dept = new Dept();
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;


        try {
            String dno = request.getParameter("dno");
            conn = DBUtil.getConnection();

            String sql = "select dname,loc as location from dept where deptno = ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,dno);

            //这个结果集只有一条记录,deptno是主键，不能重复
            rs = ps.executeQuery();

            if(rs.next()){
                String dname = rs.getString("dname");
                String location = rs.getString("location");

                dept.setDeptno(dno);
                dept.setDname(dname);
                dept.setLoc(location);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DBUtil.close(conn,ps,rs);
        }

        request.setAttribute("userDept", dept);


        String f = request.getParameter("f");
        // 转发,修改和详情都用/dept/detail，实现代码复用，即/dept/detail，实现详情和修改的在数据库查询都用/dept/detail实现
        // 即不需要再写一个edit方法去做修改的查询
        if("edit".equals(f)){
            request.getRequestDispatcher("/edit.jsp").forward(request,response);
        }else if("detail".equals(f)){
            request.getRequestDispatcher("/detail.jsp").forward(request,response);
        }
    }

    // 根据部门编号修改部门信息
    private void doModify(HttpServletRequest request, HttpServletResponse response){
        try {
            request.setCharacterEncoding("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        response.setContentType("text/html;charset=utf-8");

        String deptno = request.getParameter("deptno");
        String dname = request.getParameter("dname");
        String loction = request.getParameter("loc");

        Connection conn = null;
        PreparedStatement ps = null;
        int row = 0;

        try {
            conn = DBUtil.getConnection();

            String sql = "update dept set dname = ?,loc = ? where deptno = ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,dname);
            ps.setString(2,loction);
            ps.setString(3,deptno);

            row = ps.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DBUtil.close(conn,ps,null);
        }

        if(row == 1){
            try {
                response.sendRedirect(request.getContextPath() + "/dept/list");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            try {
                response.sendRedirect(request.getContextPath() + "/error.jsp");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
